using System;
using System.Collections;
using System.DirectoryServices;
using System.Globalization;
using System.Threading;
using Sedna.Core.Common;
using Sedna.Core.Controller;
using log4net;
using Nullables;

namespace Sedna.Core.Security
{
	public class CurrentThreadPrincipalWrapper : IPrincipalWrapper
	{

//		private ISecurityApi securityApi;
		private IPropertiesService propertiesService;


		private ILog log = LogManager.GetLogger(typeof(CurrentThreadPrincipalWrapper));

		private bool suppressDirectoryLookup = false;


		/// <summary>
		/// optional collaborator, though if not installed - some Sedna specific features might not be availabe
		/// throws ControllerConfigurationException if a feature is requested that requires SecurityApi be set up.
		/// </summary>
//		public ISecurityApi SecurityApi
//		{
//			set { securityApi = value; }
//		}

		public IPropertiesService PropertiesService
		{
			set { propertiesService = value; }
		}


		public bool SuppressDirectoryLookup
		{
			set { suppressDirectoryLookup = value; }
		}


		public string IdentityName
		{
			get
			{
				try
				{
					return Thread.CurrentPrincipal.Identity.Name;
//					if(securityApi != null)
//					{
//						return securityApi.CurrentUser.Name;
//					}
				}
				catch(Exception e)
				{
					log.Error("Unable to obtain a IUserInfo.Name from a securityApi", e);
					return Thread.CurrentPrincipal.Identity.Name;
				}
			}
		}

		public string FullName
		{
			get
			{
                try
                {
                    SednaWorkPrincipal principal = Thread.CurrentPrincipal as SednaWorkPrincipal;
                    return principal.User.FullName;
                }
			    catch(Exception ex)
			    {
                    return Thread.CurrentPrincipal.Identity.Name;
			    }
//				if(securityApi != null /*&& securityApi.CurrentUser.AuthenticationMethod == Windows*/)
//				{
//					return ExtractFullNameFromCoreIms();
//				}
//				else
				{
					//return ExtractFullNameFromActiveDirectory(Thread.CurrentPrincipal.Identity.Name);
				}
			}
		}

		public System.Globalization.CultureInfo Culture
		{
			get
			{
				return Thread.CurrentThread.CurrentCulture;
			}
		}

		public bool IsInRole(string roleName)
		{
			return Thread.CurrentPrincipal.IsInRole(roleName);
		}

		//todo: WTF?
        public int ImsUserId
		{
			get
			{
				return 1;
//				if(securityApi == null)
//				{
//					throw new ControllerConfigurationException("SecurityApi collaborator is not installed, please check the corrensponding config file");
//				}
//				return securityApi.CurrentUser.UserId;
			}
		}


		public CultureInfo DefinedCulture
		{
			get
			{
				return propertiesService.DefinedCulture;
			}
		}


		public NullableInt32 ImsOwnerId
		{
			get 
			{
				return NullableInt32.Default;
//				if(securityApi == null)
//				{
//					return NullableInt32.Default;
//				}
//				else
//				{
//					try
//					{
//						int innerOwnerId = securityApi.CurrentUser.OwnerId;
//						return innerOwnerId==Int32.MinValue?NullableInt32.Default:innerOwnerId;
//					}
//					catch(Exception e)
//					{
//						log.Error("unable to retreive current user OwnerId", e);
//						return NullableInt32.Default;
//					}
//				}
			}
		}


		public NullableInt32 DefaultSiteId
		{
			get
			{
				return NullableInt32.Default;

//				if(securityApi == null)
//				{
//					return NullableInt32.Default;
//				}
//				else
//				{
//					try
//					{
//						int innerSiteId = securityApi.CurrentUser.DefaultSiteId;
//						return innerSiteId>0?(NullableInt32) innerSiteId:NullableInt32.Default;
//					}
//					catch(Exception e)
//					{
//						log.Error("unable to retreive DefaultSiteId for a current User", e);
//						return NullableInt32.Default;
//					}
//				}
			}
		}


		private static readonly IList EMPTY_LIST = ArrayList.ReadOnly(new ArrayList());
		public IList AvailableSiteIds
		{
			get
			{
				return EMPTY_LIST;
//				if(securityApi == null)
//				{
//					return EMPTY_LIST;
//				}
//				else
//				{
//					try
//					{
//						return securityApi.CurrentUser.AvailableSiteIds;
//					}
//					catch(Exception e)
//					{
//						log.Error("unable to retreive current user AvailableSiteIds", e);
//						return EMPTY_LIST;
//					}
//				}
			}
		}

		public bool IsSiteLock
		{
			get
			{
				return false;
//				if(securityApi == null)
//				{
//					return false;
//				}
//				else
//				{
//					try
//					{
//						return securityApi.CurrentUser.IsSiteLock;
//					}
//					catch(Exception e)
//					{
//						log.Error("unable to check if a user is Site Locked", e);
//						return false;
//					}
//				}
			}
		}

		public NullableInt32 PageSize
		{
			get
			{
                SednaWorkPrincipal principal = Thread.CurrentPrincipal as SednaWorkPrincipal;
                return principal.User.RowsPerPage;
				//try
				//{
				//	return propertiesService!=null?propertiesService.PageSize:NullableInt32.Default;
				//}catch(Exception e)
				//{
			//		log.Error("unable to get PageSize", e);
		//			return NullableInt32.Default;
				//}
			}
		}


//		private string ExtractFullNameFromCoreIms()
//		{
//			if(securityApi == null)
//			{
//				throw new ControllerConfigurationException("SecurityApi collaborator is not installed, please check the corrensponding config file");
//			}
//			return securityApi.CurrentUser.FullName;
//		}

		private string ExtractFullNameFromActiveDirectory(string name)
		{
			if(suppressDirectoryLookup)
			{
				return name;
			}
			string fullName = null;
			try
			{
				string path = "WinNT://" + name.Replace('\\','/');
				DirectoryEntry de = new DirectoryEntry(path);
				if(de == null)
				{
					return name;
				}
				fullName = (string)de.Properties["FullName"][0];
			}
			catch(Exception ex)
			{
				log.Error("exception while trying to lookup an entity name for an identityname=" + name, ex);
				if(ex is System.NullReferenceException)
				{
					return name;
				}
				if(ex is System.ArgumentException)
				{
					return name;
				}
				throw;
			}
			finally
			{
				if(fullName == null || fullName.Trim() == string.Empty)
				{
					fullName = name;
				}
			}

			return fullName;
		}

	}
}
